from DemoClass import Cat

# __init__() 构造函数
# 对对象进行初始化，在实例化时被自动调用
cat = Cat("Tom")
print("print(cat): ", cat)
# <DemoClass.Cat object at 0x000001E8A0F32388>   DemoClass.Cat类型的对象，在16进制(0x)地址000001E8A0F32388


# __doc__()，打印类中最开始的文件介绍
print("cat.__doc__(): ", cat.__doc__)

# __modules__()，查看对象属于的文件
print("cat.__modules__(): ", cat.__module__)

# __class__()，查看对象的类型
print("cat.__class__(): ", cat.__class__)

# __call__()，调用
"""
函数的调用方法：

def func(a, b):
    print(a + b)
func(1,2)
"""
cat(1, 2)
print("callable(cat): ", callable(cat))

# __dict__()
"""
__dict__，查看类的成员属性。可以查看到私有对象。
实际上，原本类中定义的私有对象__privatename变成了_Cat__privatename，通过cat._Cat__privatename还是可以访问到的
这里可以发现，python的私有对象，实质上是更改了变量前面的名字（增加了_类型）。并不是真正的设置权限。
"""
print("cat.__dict__():", cat.__dict__)
# print(cat.name)
# print(cat.__privatename)     # 报错，无法直接访问私有对象
# print(cat._Cat__privatename)  # warning，可以访问到，但最好不要这么做


# __str__()
print("cat.__str__(): ", str(cat))

# __len__()
print("cat.__len__(): ", len(cat))

# __iter__()，让对象可以被迭代
for i in cat:
    print("cat", i)

# __getitem__() , __setitem__(), __delitem()
"""
dictionary的常见操作
dic = {"name":"crystal", 'age':40, 'dep': 'ccb'}
print(dic["name"])
dic["name"] = 'sniper'
print(dic["name"])
del dic['age']
print(dic)

通过cat.__dict__()，可以得到{'name': 'Tom', '_Cat__privatename': 'Tom', 'length': 10}
希望直接通过 cat['name'] 这样的方式得到 'Tom'，
这时就需要__getitem__()
"""
print("cat.__len__():", cat['name'])

# 定义了 __setitem__()之后，可以像dictionary一样修改
cat['name'] = 'new_cat_name'
print("After reset the name: ", cat['name'])

# 删除后再打印，已经没有'name'和对应的value了
del cat['name']
print(cat.__dict__)

# 重载数学运算：+ - * / % **
# __add__()
# __sub__()
# __mul__()
# __div__()
# __mod__()
# __pow__()
"""
x = 1
y = 2
print (x + y)
"""
cat3 = ('A', 3)
cat4 = ('B', 5)
# 定义了__str__()之后，打印出的是具体信息。否则打印出 <DemoClass.Cat object at 0x000001E8A0F32388> 的形式
print(cat3 + cat4)

# __del__ 析构函数
# 回收对象时调用，销毁对象。直接使用del，析构函数自动调用
del cat
# print(cat)  报错，因为对象已经被销毁
